﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using System.Transactions;
using Abp.Dependency;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Runtime.Session;
using Blog.ThirdPartyCallLogs;
using Castle.Core.Logging;
using Castle.DynamicProxy;
using Newtonsoft.Json;

namespace Blog.Interceptors
{
    public class ThirdPartyCallHelper : IThirdPartyCallHelper, ITransientDependency
    {
        private readonly IUnitOfWorkManager _unitOfWorkManager;
        private readonly IRepository<ThirdPartySystemCallLog, Guid> _thirdPartySystemCallLogRepository;
        public ILogger Logger { get; set; }
        
        public IAbpSession AbpSession { get; set; }

        public ThirdPartyCallHelper(
            IUnitOfWorkManager unitOfWorkManager,
            IRepository<ThirdPartySystemCallLog, Guid> thirdPartySystemCallLogRepository
            )
        {
            _unitOfWorkManager = unitOfWorkManager;
            _thirdPartySystemCallLogRepository = thirdPartySystemCallLogRepository;
        }

        public ThirdPartySystemCallLog CreateThirdPartySystemCallLog(IInvocation invocation)
        {
            string inputParams;
            var argumentsDictionary = CreateArgumentsDictionary(invocation.MethodInvocationTarget, invocation.Arguments);
            if (argumentsDictionary.Count == 1)
            {
                //如果只有一个参数，如只有一个input参数，则只把input参数里面的成员转换为json
                var enumerator = argumentsDictionary.GetEnumerator();
                bool isSucc = enumerator.MoveNext();
                var e = enumerator.Current;
                inputParams = JsonConvert.SerializeObject(e.Value);
            }
            else
            {
                //如果有多个参数，则转换json格式为：{参数名称1: obj, 参数名称2:obj……}
                inputParams = JsonConvert.SerializeObject(argumentsDictionary);
            }

            var thirdPartySystemCallLog = new ThirdPartySystemCallLog();

            thirdPartySystemCallLog.NatrualKeyId = Guid.Empty;//暂时无法获取
            thirdPartySystemCallLog.SourceSystem = "";//暂时无法获取
            thirdPartySystemCallLog.RequestParameters = inputParams;
            thirdPartySystemCallLog.ServiceName = invocation.TargetType.Name;
            thirdPartySystemCallLog.ClassFullName = invocation.TargetType.FullName;
            thirdPartySystemCallLog.MethodName = invocation.Method.Name;
            thirdPartySystemCallLog.InputParamClassFullName = invocation.Arguments?[0].GetType().FullName;

            return thirdPartySystemCallLog;
        }

        public async Task SaveAsync(ThirdPartySystemCallLog thirdPartySystemCallLog)
        {
            using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.Suppress))
            {
                await _thirdPartySystemCallLogRepository.InsertAsync(thirdPartySystemCallLog);
                uow.Complete();
            }
        }

        public void Save(ThirdPartySystemCallLog thirdPartySystemCallLog)
        {
            using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.Suppress))
            {
                _thirdPartySystemCallLogRepository.Insert(thirdPartySystemCallLog);
                uow.Complete();
            }
        }

        private static Dictionary<string, object> CreateArgumentsDictionary(MethodInfo method, object[] arguments)
        {
            var parameters = method.GetParameters();
            var dictionary = new Dictionary<string, object>();

            for (var i = 0; i < parameters.Length; i++)
            {
                dictionary[parameters[i].Name] = arguments[i];
            }

            return dictionary;
        }
    }
}